package com.android.kotlincoroutinemvvmdemo.view
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ViewConfiguration
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.AnticipateInterpolator
import android.view.animation.AnticipateOvershootInterpolator
import android.view.animation.BounceInterpolator
import android.view.animation.DecelerateInterpolator
import android.view.animation.OvershootInterpolator
import android.widget.OverScroller
import android.widget.Scroller
import androidx.constraintlayout.widget.ConstraintLayout
import kotlin.math.abs

class DragBounceLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private var lastY = 0f

    //private var totalMovedY = 0f

    private val configuration = ViewConfiguration.get(context)
    private val scroller = Scroller(context, DecelerateInterpolator())
    //private val scroller = OverScroller(context, BounceInterpolator())
    //private val scroller = OverScroller(context, OvershootInterpolator())
    //private val scroller = OverScroller(context, AccelerateDecelerateInterpolator())
    //private val scroller = OverScroller(context, AnticipateInterpolator())
    //private val scroller = OverScroller(context, AnticipateInterpolator())

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> {
                lastY = ev.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                val moveY = ev.rawY
                return if (abs(moveY) >= configuration.scaledTouchSlop) {
                    lastY = moveY
                    true
                } else {
                    lastY = moveY
                    super.onInterceptTouchEvent(ev)
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                performClick()
                if (!scroller.isFinished) {
                    scroller.abortAnimation()
                }
                lastY = event.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                val deltaY = (event.rawY - lastY) * DELTA_FACTOR
                //限制y轴上的拖动距离
                val maxHeight = height * MAX_DRAG_PERCENT
                //coerceIn(min,max)表示值在[max,max]区间内

                val translationY = (this.translationY + deltaY).coerceIn(-maxHeight, maxHeight)
                this.translationY = translationY

                //totalMovedY += deltaY
                //totalMovedY = totalMovedY.coerceIn(-maxHeight, maxHeight)
                //scrollTo(0, -totalMovedY.toInt())

                lastY = event.rawY
            }
            MotionEvent.ACTION_UP -> {
                val startY = translationY.toInt()

                //val startY = -totalMovedY.toInt()

                val targetY = 0
                scroller.startScroll(0, startY, 0, targetY - startY, 450)
                invalidate()
            }
        }
        return true
    }

    override fun computeScroll() {
        if (scroller.computeScrollOffset()) {
            Log.d(TAG,"scroller.currX:${scroller.currX},scroller.currY:${scroller.currY}")
            translationX = scroller.currX.toFloat()
            translationY = scroller.currY.toFloat()

            //scrollTo(scroller.currX, scroller.currY)
            //totalMovedY = scroller.currY.toFloat()

            invalidate()
        }
    }

    override fun performClick(): Boolean {
        return super.performClick()
    }

    companion object {
        private const val TAG = "DragBounceLayout"

        private const val MAX_DRAG_PERCENT = 0.625f
        private const val DELTA_FACTOR = 0.7f
    }
}